package ru.amse.tsyganov.jumleditor.graphicaleditor;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.graphics.GC;

import ru.amse.tsyganov.jumleditor.commands.Command;
import ru.amse.tsyganov.jumleditor.commands.CommandFactory;
import ru.amse.tsyganov.jumleditor.model.State;
import ru.amse.tsyganov.jumleditor.model.Transition;
import ru.amse.tsyganov.jumleditor.view.ConnectionPoint;
import ru.amse.tsyganov.jumleditor.view.lines.Line;
import ru.amse.tsyganov.jumleditor.view.lines.LineBuilder;
import ru.amse.tsyganov.jumleditor.view.lines.LinePainter;
import ru.amse.tsyganov.jumleditor.view.lines.SimpleLine;
import ru.amse.tsyganov.jumleditor.view.preferences.Colors;
import ru.amse.tsyganov.jumleditor.view.preferences.Cursors;
import ru.amse.tsyganov.jumleditor.view.representation.StateView;
import ru.amse.tsyganov.jumleditor.view.representation.TransitionView;

/*package*/ class AddTransitionMode extends EditorMode {

	private final GraphicalEditor graphicalEditor;
	
	private StateView<? extends State> sourceState;
	
	private StateView<? extends State> targetState;
	
	private ConnectionPoint sourceConnectionPoint;
	
	private ConnectionPoint targetConnectionPoint;
	
	private int currentX;
	
	private int currentY;
	
	public AddTransitionMode(GraphicalEditor graphicalEditor) {	
		this.graphicalEditor = graphicalEditor;	
	}
	
	@Override
	public void initState() {
		graphicalEditor.getCanvas().setCursor(
				Cursors.getCursorNo());
		
		graphicalEditor.getActivityGraphView().setExcludedState(null);
		graphicalEditor.getActivityGraphView().setPaintConnectionPoints(true);
		
		sourceState = null;
		targetState = null;
		graphicalEditor.getCanvas().redraw();
	}
	
	@Override
	public void mouseDoubleClick(MouseEvent e) {
	}

	@Override
	public void mouseDown(MouseEvent e) {
		sourceState = graphicalEditor.
			getActivityGraphView().getStateView(e.x, e.y);
		
		if (sourceConnectionPoint != null) {
			sourceConnectionPoint.setSelected(false);
		}
		
		if (sourceState != null) {
			sourceConnectionPoint = sourceState.getNearestConnectionPoint(e.x, e.y);
			sourceConnectionPoint.setSelected(true);
		}
		
		graphicalEditor.getActivityGraphView().setExcludedState(sourceState);
		
		targetState = null;
	}

	@Override
	public void mouseMove(MouseEvent e) {
		currentX = e.x;
		currentY = e.y;
		
		targetState = graphicalEditor.
			getActivityGraphView().getStateView(e.x, e.y);
		
		if (targetConnectionPoint != null) {
			targetConnectionPoint.setSelected(false);
		}
		
		if (targetState != null) {
			graphicalEditor.getCanvas().setCursor(
					Cursors.getCursorArrowPlus());
			
			targetConnectionPoint = targetState.getNearestConnectionPoint(e.x, e.y);
			targetConnectionPoint.setSelected(true);
		} else {
			graphicalEditor.getCanvas().setCursor(
					Cursors.getCursorNo());
			targetConnectionPoint = null;
		}
	}

	@Override
	public void mouseUp(MouseEvent e) {
		if (targetState != null) {
			assert sourceState != null;
			
			boolean duplicate = false;
			for (Transition t : sourceState.getModel().
					getStateVertex().getOutgoing()) {
				
				if (t.getTarget() == targetState.
						getModel().getStateVertex()) {
					
					duplicate = true;
					break;
				}
			}
			if (!duplicate && sourceState != targetState) {
				Transition transition = new Transition(
						sourceState.getModel().getStateVertex(), 
						targetState.getModel().getStateVertex());
				
				TransitionView<Transition> transitionView = 
					new TransitionView<Transition>(transition, 
							graphicalEditor.getActivityGraphView(),
							sourceConnectionPoint,
							targetConnectionPoint);
			
				Command newTransitionCommand = 
					CommandFactory.createNewTransitionCommand(
							transitionView);
									
				graphicalEditor.getViewsManager().executeCommand(
						newTransitionCommand);
				
				transitionView.addPropertyListener(
						graphicalEditor.getPropertyChangeListener());
			}
			graphicalEditor.setEditorMode(graphicalEditor.getSelectionMode());
			graphicalEditor.getActivityGraphView().setPaintConnectionPoints(false);
			graphicalEditor.getActivityGraphView().setExcludedState(null);
		} else {
			graphicalEditor.getActivityGraphView().setPaintConnectionPoints(true);
			graphicalEditor.getActivityGraphView().setExcludedState(null);
		}
		
		sourceState = null;
		targetState = null;
		
		if (sourceConnectionPoint != null) {
			sourceConnectionPoint.setSelected(false);
		}
		
		if (targetConnectionPoint != null) {
			targetConnectionPoint.setSelected(false);
		}
	}

	@Override
	public void paintControl(PaintEvent e, Coordinates coordinates) {
		if (sourceState != null) {
			if (sourceState.getRectangle().
					contains(currentX, currentY)) {
				
				return;
			}
			
			GC gc = e.gc;
			
			if (targetState != null) {
				Line[] lines = LineBuilder.getBrokenLine(
						sourceConnectionPoint, targetConnectionPoint);
				gc.setBackground(Colors.getBlackColor());
				gc.setForeground(Colors.getBlackColor());
				LinePainter.drawArrowedLine(gc, coordinates, lines);
			} else {
				gc.setBackground(Colors.getBlackColor());
				gc.setForeground(Colors.getBlackColor());
				LinePainter.drawArrowedLine(gc, coordinates, new SimpleLine(
						sourceConnectionPoint.getCpX(),
						sourceConnectionPoint.getCpY(),
						currentX,
						currentY), true);
				sourceState.paint(gc, coordinates);
			}
			gc.setLineStyle(SWT.LINE_SOLID);
		} 
	}

	@Override
	public void keyPressed(KeyEvent e) {	
	}

	@Override
	public void keyReleased(KeyEvent e) {
	}
}
